package org.example.demo1.service;


import org.example.demo1.Entity.ServiceInfo;
import io.fabric8.kubernetes.api.model.*;
import io.fabric8.kubernetes.client.KubernetesClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@RequiredArgsConstructor
@Slf4j
public class ServiceDiscoveryService {

    private final ClusterService clusterService;

    // 定义要发现的服务模式
    private final Map<String, List<String>> servicePatterns = Map.of(
            "grafana", Arrays.asList("grafana"),
            "prometheus", Arrays.asList("prometheus", "prometheus-server"),
            "jaeger", Arrays.asList("tracing"),
            "kiali", Arrays.asList("kiali")
    );

    public Map<String, Object> discoverMonitoringServices() {
        try (KubernetesClient client = clusterService.getClient()) {
            Map<String, Object> discoveredServices = new HashMap<>();

            // 获取所有命名空间
            List<Namespace> namespaces = client.namespaces().list().getItems();

            for (String serviceType : servicePatterns.keySet()) {
                discoveredServices.put(serviceType, null);
                List<String> patterns = servicePatterns.get(serviceType);

                // 在所有命名空间中搜索服务
                for (Namespace namespace : namespaces) {
                    String namespaceName = namespace.getMetadata().getName();

                    try {
                        List<io.fabric8.kubernetes.api.model.Service> services =
                                client.services().inNamespace(namespaceName).list().getItems();

                        for (io.fabric8.kubernetes.api.model.Service service : services) {
                            String serviceName = service.getMetadata().getName().toLowerCase();

                            // 检查服务名是否匹配
                            if (patterns.stream().anyMatch(serviceName::contains)) {
                                ServiceInfo serviceInfo = buildServiceInfo(service, namespaceName, client);
                                if (serviceInfo != null) {
                                    discoveredServices.put(serviceType, serviceInfo.toMap());
                                    log.info("发现服务: {} 在命名空间: {}", serviceName, namespaceName);
                                    break;
                                }
                            }
                        }

                        if (discoveredServices.get(serviceType) != null) {
                            break; // 找到服务后跳出命名空间循环
                        }

                    } catch (Exception e) {
                        log.warn("搜索命名空间 {} 中的服务时出错: {}", namespaceName, e.getMessage());
                    }
                }
            }

            return discoveredServices;

        } catch (Exception e) {
            log.error("服务发现失败", e);
            throw new RuntimeException("服务发现失败: " + e.getMessage());
        }
    }

    private ServiceInfo buildServiceInfo(io.fabric8.kubernetes.api.model.Service service,
                                         String namespaceName, KubernetesClient client) {
        if (service.getSpec() == null ||
                service.getSpec().getPorts() == null ||
                service.getSpec().getPorts().isEmpty()) {
            return null;
        }

        ServicePort port = service.getSpec().getPorts().get(0);
        String serviceName = service.getMetadata().getName();
        String serviceType = service.getSpec().getType();

        String url = null;
        Integer accessPort = null;

        try {
            // 根据服务类型构建访问URL
            switch (serviceType) {
                case "NodePort":
                    if (port.getNodePort() != null) {
                        accessPort = port.getNodePort();
                        // 获取节点IP（使用第一个节点的外部IP或内部IP）
                        String nodeIp = getNodeIp(client);
                        if (nodeIp != null) {
                            url = String.format("http://%s:%d", nodeIp, accessPort);
                        }
                    }
                    break;

                case "LoadBalancer":
                    if (service.getStatus() != null &&
                            service.getStatus().getLoadBalancer() != null &&
                            service.getStatus().getLoadBalancer().getIngress() != null &&
                            !service.getStatus().getLoadBalancer().getIngress().isEmpty()) {

                        LoadBalancerIngress ingress = service.getStatus().getLoadBalancer().getIngress().get(0);
                        String lbIp = ingress.getIp() != null ? ingress.getIp() : ingress.getHostname();
                        accessPort = port.getPort();
                        if (lbIp != null) {
                            url = String.format("http://%s:%d", lbIp, accessPort);
                        }
                    }
                    break;

                case "ClusterIP":
                default:
                    accessPort = port.getPort();
                    url = String.format("http://%s.%s.svc.cluster.local:%d",
                            serviceName, namespaceName, accessPort);
                    break;
            }

        } catch (Exception e) {
            log.warn("构建服务 {} 的访问URL时出错: {}", serviceName, e.getMessage());
        }

        return ServiceInfo.builder()
                .available(true)
                .name(serviceName)
                .namespace(namespaceName)
                .port(accessPort != null ? accessPort.toString() : port.getPort().toString())
                .type(serviceType)
                .url(url)
                .build();
    }

    private String getNodeIp(KubernetesClient client) {
        try {
            List<Node> nodes = client.nodes().list().getItems();

            for (Node node : nodes) {
                if (node.getStatus() != null && node.getStatus().getAddresses() != null) {
                    // 优先使用外部IP
                    for (NodeAddress address : node.getStatus().getAddresses()) {
                        if ("ExternalIP".equals(address.getType())) {
                            return address.getAddress();
                        }
                    }
                    // 如果没有外部IP，使用内部IP
                    for (NodeAddress address : node.getStatus().getAddresses()) {
                        if ("InternalIP".equals(address.getType())) {
                            return address.getAddress();
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.warn("获取节点IP时出错: {}", e.getMessage());
        }
        return "localhost"; // 回退到localhost
    }
}
